package com.sv.base.repository;

import java.sql.SQLException;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;

import com.ibatis.sqlmap.client.SqlMapClient;
import com.sv.generic.SqlMapSpace;
import com.sv.utils.SqlMapClientFactory;

@Repository
public class BaseRepository<T, U> implements IRepository<T, U> {

    private static final String COUNT_BY_EXAMPLE = ".ibatorgenerated_countByExample";

    private static final String DELETE_BY_EXAMPLE = ".ibatorgenerated_deleteByExample";

    private static final String DELETE_BY_PRIMARYKEY = ".ibatorgenerated_deleteByPrimaryKey";

    private static final String INSERT = ".ibatorgenerated_insert";

    // private static final String INSERT_SELECTIVE =
    // ".ibatorgenerated_insertSelective";

    private static final String SELECT_BY_EXAMPLE = ".ibatorgenerated_selectByExample";

    private static final String SELECT_BY_PRIMARYKEY = ".ibatorgenerated_selectByPrimaryKey";

    private static final String UPDATE_BY_EXAMPLESELECTIVE = ".ibatorgenerated_updateByExampleSelective";

    // private static final String UPDATE_BY_EXAMPLE =
    // ".ibatorgenerated_updateByExample";

    private static final String UPDATE_BY_PRIMARYKEYSELECTIVE = ".ibatorgenerated_updateByPrimaryKeySelective";

    // private static final String UPDATE_BY_PRIMARYKEY =
    // ".ibatorgenerated_updateByPrimaryKey";
    //
    // private static final String SELECT_BY_EXAMPLE_WITHBLOBS =
    // ".ibatorgenerated_selectByExampleWithBLOBs";

    @Autowired
    @Qualifier("sqlMapClient")
    private SqlMapClient sqlMapClient;

    public int countByExample(U u) throws SQLException {
        return (Integer) sqlMapClient.queryForObject(
                getSqlMapNameSpaceByExample(u) + COUNT_BY_EXAMPLE, u);
    }

    public int deleteByExample(U u) throws SQLException {
        return sqlMapClient.delete(getSqlMapNameSpaceByExample(u)
                + DELETE_BY_EXAMPLE, u);
    }

    public int deleteByPrimaryKey(T t) throws SQLException {
        return sqlMapClient.delete(
                getSqlMapNameSpace(t) + DELETE_BY_PRIMARYKEY, t);
    }

    public void insert(T t) throws SQLException {
        SqlMapClientFactory.getSqlMapClient().insert(getSqlMapNameSpace(t) + INSERT, t);

    }

    public void insertSelective(T t) throws SQLException {
        sqlMapClient.insert(getSqlMapNameSpace(t), t);
    }

    @SuppressWarnings("unchecked")
    public List<T> selectByExample(U u) throws SQLException {
        return (List<T>) sqlMapClient.queryForList(
                getSqlMapNameSpaceByExample(u) + SELECT_BY_EXAMPLE, u);
    }

    @SuppressWarnings("unchecked")
    public T selectByPrimaryKey(T t) throws SQLException {
        return ((T) sqlMapClient.queryForObject(getSqlMapNameSpace(t)
                + SELECT_BY_PRIMARYKEY, t));
    }

    public int updateByExampleSelective(U u) throws SQLException {

        return sqlMapClient.update(getSqlMapNameSpaceByExample(u)
                + UPDATE_BY_EXAMPLESELECTIVE, u);
    }

    public int updateByPrimaryKeySelective(T t) throws SQLException {

        return sqlMapClient.update(getSqlMapNameSpace(t)
                + UPDATE_BY_PRIMARYKEYSELECTIVE, t);
    }

    public SqlMapClient getSqlMapClient() {
        return sqlMapClient;
    }

    public void setSqlMapClient(SqlMapClient sqlMapClient) {
        this.sqlMapClient = sqlMapClient;
    }

    private String getSqlMapNameSpace(T t) {
        SqlMapSpace sqlMap = t.getClass().getSuperclass()
                .getAnnotation(SqlMapSpace.class);
        if (sqlMap == null) {
            sqlMap = t.getClass().getAnnotation(SqlMapSpace.class);
        }
        return sqlMap.name();
    }

    private String getSqlMapNameSpaceByExample(U u) {
        SqlMapSpace sqlMap = u.getClass().getSuperclass()
                .getAnnotation(SqlMapSpace.class);
        if (sqlMap == null) {
            sqlMap = u.getClass().getAnnotation(SqlMapSpace.class);
        }
        return sqlMap.name();
    }

}
